<?php

/**
 * Модель "Пользователь"
 * Отвечает в основном за работу с разделом пользователя
 * Может применятся и в других разделах сайта
 */
class User
{

//// Манипуляторы "первого сорта" (Inline methods)

    // bool Авторизован ли пользователь
    public static function isLogged()
    {
        return isset($_SESSION['user']);
    }

    // void Авторизовывает пользователя
    public static function auth($userId)
    {
        $_SESSION['user'] = $userId;
    }

    // void Деавторизовывает пользователя
    public static function deauth()
    {
        unset($_SESSION['user']);
    }

    // {Object} user Возвращает ячейку в таблице "Пользователя" по Id
    public static function getUser($userId)
    {
        return R::load('user', $userId);
    }

    // Переадресовывает на главную страницу
    public static function LinkToIndex()
    {
        header('Location: /');
    }

    // Переадресовывает на страницу авторизации
    public static function LinkToAuth()
    {
        header('Location: /auth/');
    }

    // Переадресовывает в профиль
    public static function LinkToProfile()
    {
        header('Location: /profile/');
    }

//// Методы "второго сорта"


    // Вернёт id авторизованного пользователя, если таковой есть
    // Если не вернуло то переадресует на страницу авторизации
    public static function checkLogged()
    {
        if (isset($_SESSION['user'])) return $_SESSION['user'];
        User::LinkToAuth();
    }

    // Вернёт результат на вопрос "Пользователь не авторизован?"
    // Если не вернёт то переадресует на главную страницу
    public static function checkNotLogged()
    {
        if (!isset($_SESSION['user'])) return true;
        User::LinkToIndex();
    }

//// Методы "Третьего сорта"

    /**
     * Метод регистрации нового пользователя
     *
     * @param $_POST Суперглобальный массив с данными введёнными пользователем
     * @return Переадресация на страницу с профилем нового пользователя
     */
    public static function register()
    {
        $user = R::dispense('user');
        $user->username = $_POST['username'];
        $user->email = $_POST['email'];
        $user->password = password_hash($_POST['password'], PASSWORD_DEFAULT);
        $user->role = 'user'; // По умолчанию привиллегии
        $user->avatar = 'https://mdbootstrap.com/img/new/standard/city/026.jpg';

        $userId = R::store($user);

        User::auth($userId);
        User::LinkToProfile();
    }

    /**
     * Метод удаление аккаунта пользователя ( Разрегистрация )
     *
     * @param $_POST Суперглобальный массив с данными введёнными пользователем
     * @param int userId <p> id пользователя, которого ждёт разрегистрация </p>
     * @return Переадресация на главную страницу
     * */
    public static function UnRegister($userId)
    {
        // Если маркер удаления страницы верный, то
        if ($_POST['delete-account-marker'] == 'KONO DIO DA') {
            // Получаем обьект пользователя
            $user = R::load('user', $userId);

            // Деавторизуем пользователя
            User::deauth();

            // Если по пути из записи в бд есть файл, то удаляем его
            if (file_exists(ROOT . $user->avatar)) unlink(ROOT . $user->avatar);

            // Удаляем запись в БД
            R::trash($user);

            // Перенаправляем его на главную страницу
            User::LinkToIndex();
        }
    }

    /**
     * Метод верификации данных введёнными пользователями.
     * Для регистрации или модификакии существующего профиля.
     *
     * @param $_POST Суперглобальный массив с данными введёнными пользователем
     * @param {optional} $userId Параметр, отличающий
     * регистрацию нового пользователя, или модификацию существующего
     *
     * @return [Array|Bool] errors Обьект, характеризующий наличие невалидных данных
     * */
    public static function verifyUserData($userId = 0)
    {
        $errors = false;

        // Базовые проверки
        if (strlen($_POST['username']) < 2) $errors[] = 'Слишком короткое имя пользователя!';

        if (strlen($_POST['password']) < 2) $errors[] = 'Слишком короткий пароль!';

        if ($_POST['password'] != $_POST['pass_c']) $errors[] = 'Подтверждение пароля введено неправильно!';

        // Если базовые проверки пройдены:
        if (!$errors) {
            // Получаем количество записей в БД с введённым именем пользователя
            $count = R::count(
                'user', 'username = :username AND id != :user_id',
                [':username' => $_POST['username'], ':user_id' => $userId]
            );

            // Если больше 0(равен 1), значит этот юзернейм занят
            if ($count) $errors[] = "Уже существует учётная запись с этим Юзернеймом";
        }

        return $errors;
    }

    /**
     * Вход в учётную запись пользователя
     *
     * @param $_POST Суперглобальный массив с данными введёнными пользователем
     *
     * @return [Array|Bool] errors Обьект, характеризующий наличие невалидных данных
     */
    public static function checkLogin()
    {
        $errors = [];
        // Базовые проверки:
        if (empty($_POST['username'])) $errors[] = "Введите имя пользователя!";
        if (empty($_POST['password'])) $errors[] = "Введите пароль!";
        // Если базовые проверки пройдены:
        if (empty($errors)) {
            // Получаем запись в БД с введёнными логином и паролем пользователя
            $user = R::findOne(
                'user',
                'username = :username',
                [':username' => $_POST['username']]
            );

            if (!$user)
            {
                $errors[] = 'Пользователь не зарегестрирован';
            }

            if (empty($errors))
            {
                if ($user['counter'] >= 3) {
                    $user['counter'] = 0;
                    $user['baned_at'] = time() + 60 * 5;
                    R::store($user);
                }
                if (!empty($user['baned_at'])) {
                    if ($user['baned_at'] > time()) {
                        $errors[] = 'Вы были заблокированы за неудачные попытки входа' .' '. date("d-m-Y H:i:s", $user['baned_at']);;
                    } else {
                        $user['baned_at'] = null;
                        R::store($user);
                        // Если такая запись есть
                        if ($user && password_verify($_POST['password'], $user->password)) {
                            // Авторизуем пользователя
                            User::auth($user->id);
                            // Переадресовываем его в его профиль
                            User::LinkToProfile();
                        } else {
                            $user['counter'] = $user['counter'] + 1;
                            R::store($user);
                            // Если пользователя в БД с такими данными нет
                            $errors[] = 'Warning !!! Неправильный логин или пароль!';

                        }
                    }
                } else {
                    // Если такая запись есть
                    if ($user && password_verify($_POST['password'], $user->password)) {
                        // Авторизуем пользователя
                        User::auth($user->id);
                        // Переадресовываем его в его профиль
                        User::LinkToProfile();
                    } else {
                        $user['counter'] = $user['counter'] + 1;
                        R::store($user);
                        // Если пользователя в БД с такими данными нет
                        $errors[] = 'Warning !!! Неправильный логин или пароль!';

                    }
                }
            }


        }

        return $errors;
    }

    /**
     * Модификация учётных данных пользователя
     *
     * @param $_POST Суперглобальный массив с данными введёнными пользователем
     * @param int userId <p> id пользователя, данные которого будут изменены </p>
     *
     * @return [Array|Bool] errors Обьект, характеризующий наличие невалидных данных
     */
    public static function modify($userId)
    {
        // Валидация данных
        $errors = User::verifyUserData($userId);

        // Если был загружен файл
        if (!empty($_FILES['file-upload']['tmp_name'])) {
            // Узнаём тип файла, разбиваем его в массив
            // ["type"]=> string(9) "image/png"
            // [0] Тип файлы [1] Формат этого типа
            $typefile = explode('/', $_FILES['file-upload']['type']);

            // Если тип файла не картинка
            if ($typefile[0] != "image") {
                $errors[] = 'Неправильный тип файла!';
            }
        }
        // Конец валидации данных

        // Если ошибок нет
        if (!$errors) {
            $user = R::load('user', $userId);

            $user->username = $_POST['username'];
            $user->password = password_hash($_POST['password'], PASSWORD_DEFAULT);
            $user->email = $_POST['email'];
            $user->color = $_POST['color'];
            $user->date = $_POST['date'];
            $user->about = $_POST['about'];

            // avatar loaded
            if (!empty($_FILES['file-upload']['tmp_name'])) {

                $uploadInternalPath = '/upload/images/avatar/';// Путь до файла(для ссылки фронтенд)
                $uploaddir = ROOT . $uploadInternalPath;// Путь до файла(для помещения в директорию)

                $uploadInternalFile = $userId . '.' . $typefile[1];// Название файла (для сслыки фронтенд)
                $uploadfile = $uploaddir . $uploadInternalFile;// Путь по которому будет лежать файл(для помещения в директорию)

                // Если по этому пути уже лежит файл, то удаляем его
                if (file_exists($uploadfile)) {
                    unlink($uploadfile);
                }

                // Если по пути из записи в бд есть файл, то удаляем его
                // Двойная работа, ну и похуй
                if (file_exists(ROOT . $user->avatar)) {
                    unlink(ROOT . $user->avatar);
                }

                // Помеаем файл но указанный путь
                if (move_uploaded_file($_FILES['file-upload']['tmp_name'], $uploadfile)) {
                    // Если всё прошло успешно, то записываем путь до него в БД
                    $user->avatar = $uploadInternalPath . $uploadInternalFile;
                } else {
                    // Иначе АХТУНГ, Убиваем скрипт
                    die("Кончилась память на сервере, или другая ошибка");
                }
            }

            R::store($user);
            User::LinkToProfile();
        }

        return $errors;
    }
}
